package com.manuserve.mountainduck.kernel;


/**
 * Le canard
 * Created by ecervetti on 01/03/14.
 */



import java.util.Hashtable;

import android.graphics.PointF;

public class Duck  {

    float i = 0f ;
    float j = 0f ;
    float timeTrajectoire = 2000 ;
    Univers univers = null ;
    float bitchness = 0 ; //0->gentil, 1->connard
    Trajectoire trajectoire = null ;
    //Hashtable<Integer,Colonne> data ;


    public Duck(Univers univers) {
        this.univers =  univers ;
        i = 3 ;
        this.j = (float) (this.univers.data.get((int) this.i).height+1 );
        this.trajectoire = new Trajectoire(this) ;
        this.decideNewTrajectoire(this.timeTrajectoire,false,false);
    }

    public void physics(float timeIntervallSinceLastCalc) {
        Duck thisDuck = this ;
        //Vol du canard
        Trajectoire trajectoire = thisDuck.trajectoire ;
        if(!trajectoire.ready)
            return ;

        trajectoire.t   += timeIntervallSinceLastCalc ;

        //Le canard a fini son saut
        if( trajectoire.totalTime < trajectoire.t ) {
            thisDuck.i = trajectoire.toI ;
            thisDuck.j = trajectoire.toJ ;
            thisDuck.trajectoire.ready = false ;
            if(thisDuck.bitchness<1) {
                thisDuck.bitchness+=0.025;
             }
            if(thisDuck.bitchness>1) {
                thisDuck.bitchness=1;
            }

            if( true && thisDuck.univers.selectedCol != thisDuck.i) {
                thisDuck.univers.endJourney();
                return ;
            }
            //Le canard a réussi son saut
            thisDuck.univers.ihm.alerteBing();
            float timeTrajectoireSouhaite = (float) (thisDuck.timeTrajectoire - ( thisDuck.timeTrajectoire*thisDuck.bitchness)*Math.random());
            thisDuck.decideNewTrajectoire(timeTrajectoireSouhaite,false,false);

        } else {
            PointF calcul = thisDuck.trajectoire.calc(trajectoire.t) ;
            thisDuck.i      = calcul.x ;
            thisDuck.j      = calcul.y ;

        }
    }


      public void decideNewTrajectoire(float wishedTime,boolean depassementAutorise,boolean trajPlateAutorisee) {
        Duck thisDuck = this ;
        thisDuck.trajectoire.originI = thisDuck.i ;
        thisDuck.trajectoire.originJ = thisDuck.j ;
        PointF calcul ;
        boolean isCollision ;
        boolean presenceEchecDepassement = false ;
        Hashtable<Integer,Integer> tabPossiblesTrajectoires = new Hashtable<Integer, Integer>();
        Hashtable<Integer,Float> tabSympathieTrajectoire = new Hashtable<Integer,Float>();
        float t ;
        int i ;
        float timeStep ;
        float minSympathie = 0 ;
        float maxSympathie = -100000 ;
        float meilleurI = 0 ;
        float sympathieCase ;

        float maxAutorise = ( 1 + thisDuck.univers.jPointerIHM + thisDuck.univers.ihm.discrWidth*thisDuck.univers.pente/2 + thisDuck.univers.ihm.discrWidth )  ;

        for( i=thisDuck.univers.lastCreatedX-1;i>thisDuck.i;i--) {
            thisDuck.trajectoire.toI = i ;
           // thisDuck.trajectoire.drawtoI = i ;
            thisDuck.trajectoire.toJ = thisDuck.univers.data.get((int) thisDuck.trajectoire.toI).height +1 ;
            //On ne saute pas vers un point plus bas
            if(! trajPlateAutorisee && thisDuck.trajectoire.toJ <= (1+thisDuck.j))
                continue ;
            //plus la somme de la valeur de la case gauche et celle de la case droite sont negatives, plus la case est "sympa" (un creux autour)
            sympathieCase = 2 * thisDuck.trajectoire.toJ
                    - thisDuck.univers.data.get((int) thisDuck.trajectoire.toI - 1).height
                    - thisDuck.univers.data.get((int) thisDuck.trajectoire.toI + 1).height  ;
            //Plus le canard est un enfoiré, plus on atténue la sympathie de la case
            //Plus il est gentil, plus on la flatte
            //console.log(sympathieCase);
            sympathieCase = (float) ( sympathieCase*Math.tan(Math.PI*0.7*(0.5-thisDuck.bitchness)) ) ;

            if(minSympathie > sympathieCase)
                minSympathie = sympathieCase ;
            if(maxSympathie < sympathieCase) {
                maxSympathie = sympathieCase ;
                meilleurI = i ;
            }
            thisDuck.trajectoire.resolve(wishedTime);
            //La trajectoire ne sort pas de l'écran ?
            if( ! depassementAutorise && thisDuck.trajectoire.maximum >maxAutorise) {
                presenceEchecDepassement = true ;
                continue ;
            }
            //Pas de collision ?
            isCollision = false ;
            timeStep = wishedTime/(i-thisDuck.i) ;
            for(t=timeStep/2;t<wishedTime;t+=timeStep) {
                calcul = thisDuck.trajectoire.calc(t) ;
                if( calcul.y  < thisDuck.univers.data.get( Math.round(calcul.x ) ).height +1 ) {
                    isCollision = true ;
                    break ;
                }
                calcul = thisDuck.trajectoire.calc(t-timeStep/2) ;
                if( calcul.y  < thisDuck.univers.data.get( Math.round(calcul.x ) ).height +1 ) {
                    isCollision = true ;
                    break ;
                }
            }

            if(  isCollision) {
                continue ;
            }
            tabPossiblesTrajectoires.put(tabPossiblesTrajectoires.size(), i) ;
            tabSympathieTrajectoire.put(tabPossiblesTrajectoires.size()-1,sympathieCase) ;
        }

        if( tabPossiblesTrajectoires.size() == 0) {

            if(depassementAutorise && trajPlateAutorisee) {
                //On a rien trouvé malgré tout les bypass. Le canard ne peut hélas pas trouver de trajectoire.
                return  ;
            }

            //2->On a tenté de trouver sans succes un chemin sans collisions en baissant le temps de saut ou 1->le temps initial était trop petit pour une trajectoire sans collision
            if( ! presenceEchecDepassement && ! depassementAutorise) {
                thisDuck.decideNewTrajectoire(wishedTime+100,true,false);
                return ;
            //1->La demande initiale de temps de saut ne peut pas se faire sans déplacement
            } else if( ! depassementAutorise   ) {
                if(wishedTime<200) {
                    //j'ai diminué sans trouver de collision, j'augmente en acceptant les déplacements
                    thisDuck.decideNewTrajectoire(wishedTime+100,true,false);
                    return ;
                } else {
                    thisDuck.decideNewTrajectoire(wishedTime-100,false,false);
                    return ;
                }

            //3->on va prendre le plus petit dépassement n'impliquant pas une collision
            } else {
                if(wishedTime>(this.timeTrajectoire+1000)) {
                    //On est remonté, mais sans rien trouver. C'est qu'il n'y a que des cases plates. On trouve une trajectoire plate, tant pis
                    thisDuck.decideNewTrajectoire(wishedTime-1000,true,true);
                    return ;
                }
                thisDuck.decideNewTrajectoire(wishedTime+100,true,false);
                return ;
            }
        }
        for(i=0;i<tabSympathieTrajectoire.size();i++) {
            tabSympathieTrajectoire.put(i,tabSympathieTrajectoire.get(i)+1-minSympathie);
        }

        if(thisDuck.bitchness<0.1) {
            thisDuck.trajectoire.toI = meilleurI ;
        } else {
            thisDuck.trajectoire.toI = tabPossiblesTrajectoires.get(thisDuck.roueDeLaFortune(tabSympathieTrajectoire)) ;
        }
            thisDuck.trajectoire.toJ = thisDuck.univers.data.get((int) thisDuck.trajectoire.toI).height +1 ;
            thisDuck.trajectoire.resolve(wishedTime);
            thisDuck.trajectoire.ready = true ;
        }


        public int roueDeLaFortune (Hashtable<Integer,Float> tab) {
            float l = 0 ;
            Integer i ;
            for(i=0;i<tab.size();i++) {
                l+=tab.get(i);
            }
            float bing = ((float) Math.random()*l);
            l = 0 ;
            for(i=0;i<tab.size();i++) {
                l+=tab.get(i);
                if(l>=bing) {
                    return i ;
                }
            }
            return -1 ;
        }

    }


